package mobile.pubcrawler;

import java.io.IOException;
import java.util.List;
import java.util.Locale;

import android.content.Context;
import android.location.Address;
import android.location.Criteria;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;

public class GPSManager implements LocationListener {
	
	private static GPSManager instance;
	private Context context;
	private LocationManager locationManager;
	
	private double latitude;
	private double longitude;
	private double old_lat = 0;
	private double old_lng = 0;
	
	// die ermittelte Adresse der aktuellen Position
	private Address currentAddress;
	
	public GPSManager(Context context) {
		
		this.context = context;
        locationManager = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
        
        Criteria criteria = new Criteria();
        criteria.setAccuracy(Criteria.ACCURACY_FINE);
        criteria.setAltitudeRequired(false);
        criteria.setBearingRequired(false);
        criteria.setCostAllowed(true);
        criteria.setPowerRequirement(Criteria.NO_REQUIREMENT);
        
        String provider = locationManager.getBestProvider(criteria, true);
        locationManager.requestLocationUpdates(provider, 2000, 10, this);
        Location location = locationManager.getLastKnownLocation(provider);
        updateWithNewLocation(location);
				
	}
	
	public synchronized static void init(Context context){
		 if (instance == null) instance = new GPSManager(context);
	}
	
	public synchronized static GPSManager getInstance(){
		return instance;
	}

	//@Override
	public void onLocationChanged(Location location) {
		updateWithNewLocation(location);
	}

	//@Override
	public void onProviderDisabled(String provider) {
		updateWithNewLocation(null);		
	}

	//@Override
	public void onProviderEnabled(String provider) {}

	//@Override
	public void onStatusChanged(String provider, int status, Bundle extras) {}

    private void updateWithNewLocation(Location location) {
    	
    	if (location!=null) {
    		latitude = location.getLatitude();
    		longitude = location.getLongitude();
    		if (getDistance(latitude, longitude, old_lat, old_lng)>100) {
    			old_lat = latitude;
    			old_lng = longitude;
    			currentAddress = getAddress(true,0,0);
    		}
    	}

    }
    
    public double getLatitude() {
    	return latitude;
    }
    
    public double getLongitude() {
    	return longitude;
    }
    
    public Address getCurrentAddress() {
    	return currentAddress;
    }
    
    public Address getAddress(boolean current, double p_lat, double p_lng) {
    	Geocoder geocoder = new Geocoder(context, Locale.getDefault());
    	List<Address> result = null;
    	try {
			if (current) 
				result = geocoder.getFromLocation(latitude, longitude, 4);
			else
				result = geocoder.getFromLocation(p_lat, p_lng, 4);
		} catch (IOException e) { e.printStackTrace(); }
		if (result!=null && result.size()>0) return result.get(0); else return null;
    }
    
    public static long getDistance(double lat1, double lon1, double lat2, double lon2) {
    	int EARTH_RADIUS_KM = 6371;
    	double lat1Rad = Math.toRadians(lat1);
        double lat2Rad = Math.toRadians(lat2);
        double deltaLonRad = Math.toRadians(lon2 - lon1);
        return Math.round(1000*(Math.acos(Math.sin(lat1Rad) * Math.sin(lat2Rad) + Math.cos(lat1Rad) * Math.cos(lat2Rad) * Math.cos(deltaLonRad)) * EARTH_RADIUS_KM));
    }
    
}
